class Snake {
   // 表示蛇头的元素
   head: HTMLElement;

   // 蛇的身体（包括蛇头）
   bodies: HTMLCollection;

   // 获取蛇的容器
   element: HTMLElement;
   constructor() {
      // querySelector只取一个
      this.head = document.querySelector('#snake > div') as HTMLElement;

      this.element = document.getElementById('snake')!

      this.bodies = this.element.getElementsByTagName('div');
   }

   // 获取蛇的坐标（蛇头坐标）
   get X() {
      return this.head.offsetLeft;
   }

   // 获取蛇的Y轴坐标
   get Y() {
      return this.head.offsetTop;
   }

   // 设置蛇头的坐标
   set X(val: number) {

      //  如果新值和旧值相同，则直接返回不再修改
      if (this.X === val) {
         return
      }

      // X的值的合法范围0-290之间
      if (val < 0 || val > 290) {
         throw new Error('蛇撞强了')
      }

      // 修改x时，是在修改水平坐标，蛇在左右移动，蛇在向左移动时，不能向右掉头，反之亦然
      if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === val) {
         // console.log('掉头了');
         // 如果发生了掉头，让蛇向反方向继续移动
         if (val > this.X) {
            val = this.X - 10
         }
         else {
            val = this.X + 10
         }
      }
      //移动身体
      this.moveBody()
      this.head.style.left = val + 'px'

      //检查是否撞到自己
      this.checkHeadBody()
   }

   set Y(val: number) {
      if (this.Y === val) {
         return
      }
      if (val < 0 || val > 290) {
         throw new Error('蛇撞强了')
      }

      if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === val) {
         // console.log('掉头了');
         // 如果发生了掉头，让蛇向反方向继续移动
         if (val > this.Y) {
            val = this.Y - 10
         }
         else {
            val = this.Y + 10
         }
      }

      //移动身体
      this.moveBody()
      this.head.style.top = val + 'px'

      //检查是否撞到自己
      this.checkHeadBody()
   }

   // 蛇增加身体的方法
   addBody() {
      // 向element中添加一个div
      this.element.insertAdjacentHTML("beforeend", "<div></div>");
   }

   // 添加一个蛇身体移动的方法
   moveBody() {
      /*
             *   将后边的身体设置为前边身体的位置
             *       举例子：
             *           第4节 = 第3节的位置
             *           第3节 = 第2节的位置
             *           第2节 = 蛇头的位置
             * */

      for (let i = this.bodies.length - 1; i > 0; i--) {
         // 获取前边身体的位置
         let X = (this.bodies[i - 1] as HTMLElement).offsetLeft;
         let Y = (this.bodies[i - 1] as HTMLElement).offsetTop;

         (this.bodies[i] as HTMLElement).style.left = X + 'px';
         (this.bodies[i] as HTMLElement).style.top = Y + 'px';

      }

   }


   // 检查蛇头是否撞到身体的方法
   checkHeadBody() {
      // 获取所有的身体，检查其是否和蛇头的坐标发生重叠
      for (let i = 1; i < this.bodies.length; i++) {
         let bd = this.bodies[i] as HTMLElement;
         if (this.X === bd.offsetLeft && this.Y === bd.offsetTop) {
            // 进入判断说明蛇头撞到了身体，游戏结束
            throw new Error('撞到自己了！');
         }
      }
   }
}
export default Snake;